﻿using System;
using System.Linq;
using System.Security;
using System.Security.Principal;
using DddCms.Application.Dto;
using DddCms.Application.Dto.User;
using DddCms.Domain.Factory;
using DddCms.Domain.Model;
using DddCms.Domain.Repository;
using DddCms.Domain.Utility;
using Microsoft.Practices.Unity;
using DddCms.Domain.ServiceModel;

namespace DddCms.Application
{
    public interface IUserApp
    {
        /// <summary>
        /// Gets the update user.
        /// </summary>
        /// <param name="principal">The principal.</param>
        /// <returns></returns>
        UserDto getUser(string name);
        /// <summary>
        /// Creates the user.
        /// </summary>
        /// <param name="userValue">The user value.</param>
        /// <returns></returns>
        bool CreateUser(UserDto userValue);
        /// <summary>
        /// Gets the roles for user.
        /// </summary>
        /// <param name="username">The username.</param>
        /// <returns></returns>
        string[] GetRolesForUser(string username);
        /// <summary>
        /// Validates the password.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="password">The password.</param>
        /// <returns></returns>
        bool Validate(string name, string password);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="username"></param>
        /// <returns></returns>
        bool AlreadyExist(string username);
    }

    /// <summary>
    /// 
    /// </summary>
    public class UserApp : IUserApp
    {
        /// <summary>
        /// 
        /// </summary>
        [Dependency]
        public IRepository Repository { get; set; }
        /// <summary>
        /// 
        /// </summary>
        [Dependency]
        public IValidate Validate { get; set; }
        /// <summary>
        /// 
        /// </summary>
        [Dependency]
        public IUserFactory UserFactory { get; set; }

        [Dependency]
        public IMembershipService MembershipService { get; set; }
        /// <summary>
        /// Gets the update user.
        /// </summary>
        /// <param name="securityContextUser">The security context user.</param>
        /// <returns></returns>
        public UserDto getUpdateUser(IPrincipal securityContextUser)
        {
            if (!securityContextUser.Identity.IsAuthenticated) throw new SecurityException("Récuperation de donné sensible");
            if (!securityContextUser.IsInRole("user")) throw new SecurityException("Récuperation de donné sensible");

            User user = Repository.Users.Single(u => u.UserName == securityContextUser.Identity.Name);

            return user.toDto();
        }

        /// <summary>
        /// Creates the user.
        /// </summary>
        /// <param name="userValue">The user value.</param>
        /// <returns></returns>
        public bool CreateUser(UserDto userValue)
        {
            Validate.Valid<UserDto>(userValue, "Create");
            
            return UserFactory.CreateUser(
                userValue.Username, 
                userValue.Password, 
                userValue.Email, 
                userValue.PasswordQuestion, 
                userValue.PasswordAnswer);
        }
       
        /// <summary>
        /// 
        /// </summary>
        /// <param name="username"></param>
        /// <returns></returns>
        public string[] GetRolesForUser(string username)
        {
            return Repository.Users
                .FindByName(username)
                .GetRoles();
        }

        /// <summary>
        /// Gets the update user.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public UserDto getUser(string name)
        {
            throw new NotImplementedException();
        }


        /// <summary>
        /// Validates the specified username.
        /// </summary>
        /// <param name="username">The username.</param>
        /// <param name="password">The password.</param>
        /// <returns></returns>
        bool IUserApp.Validate(string username, string password)
        {
            Validate.Null(username);
            Validate.Null(password);

            return MembershipService.ValidatePassword(username, password);
        }


        public bool AlreadyExist(string username)
        {
            Validate.Null(username);
            return Repository.Users.Any(u => u.UserName == username);
        }
    }
}
